package com.ppt.android.common.coroutine

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import kotlinx.coroutines.*
import java.io.Closeable

/**
 *  desc  :
 *              此类用于开启协程，并自动捕获异常
 *
 *              在FragmentActivity、 ViewModel环境下，使用 [rxLifeScope.launch] 方式开启协程，会在页面销毁时，自动关闭协程  (注意：这里的rxLifeScope是变量，不是类名)
 *
 *              其它环境下，需要拿到 [RxLifeScope.launch]方法的返回值后，手动调用[Job.cancel]方法关闭协程
 * @author ZouJiaCai
 * @since 2023/3/21 18:20
 */
class RxLifeScope : Closeable, LifecycleEventObserver {
    // 使用 SupervisorJob 确保子协程失败不会影响父协程
    private val parentJob = SupervisorJob()

    // 协程作用域，使用 Dispatchers.Main.immediate 确保在主线程执行
    private val coroutineScope = CoroutineScope(Dispatchers.Main.immediate + parentJob)

    // 监听的生命周期事件
    private var lifeEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY

    // 关联的生命周期对象
    private var lifecycle: Lifecycle? = null

    // 用于存储生命周期观察者
    private var lifecycleObserver: LifecycleEventObserver? = null

    constructor() {
        // 基本构造函数
    }

    constructor(
        owner: LifecycleOwner,
        lifeEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY
    ) : this(owner.lifecycle, lifeEvent)

    constructor(
        lifecycle: Lifecycle?,
        lifeEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY
    ) {
        this.lifeEvent = lifeEvent
        this.lifecycle = lifecycle

        lifecycle?.let {
            if (it.currentState != Lifecycle.State.DESTROYED) {
                // 创建生命周期观察者
                lifecycleObserver = LifecycleEventObserver { source, event ->
                    if (lifeEvent == event) {
                        close()
                        lifecycle.removeObserver(this)
                    }
                }

                // 添加观察者
                lifecycleObserver?.let { observer ->
                    it.addObserver(observer)
                }
            } else {
                // 如果已经销毁，立即关闭
                close()
            }
        }
    }

    fun launch(block: suspend CoroutineScope.() -> Unit): Job {
        return launch(block, null)
    }

    /**
     * @param block     协程代码块，运行在UI线程
     * @param onError   异常回调，运行在UI线程
     * @param onStart   协程开始回调，运行在UI线程
     * @param onFinally 协程结束回调，不管成功/失败，都会回调，运行在UI线程
     */
    fun launch(
        block: suspend CoroutineScope.() -> Unit,
        onError: ((Throwable) -> Unit)? = null,
        onStart: (() -> Unit)? = null,
        onFinally: (() -> Unit)? = null
    ): Job {
        return coroutineScope.launch {
            try {
                // 启动前回调
                onStart?.invoke()

                // 执行协程块
                block()
            } catch (e: Throwable) {
                // 处理异常
                if (onError != null) {
                    onError(e)
                } else {
                    // 默认打印异常堆栈
                    e.printStackTrace()
                }
            } finally {
                // 最终回调
                onFinally?.invoke()
            }
        }
    }

    override fun close() {
        // 取消所有协程
        parentJob.cancel()

        // 移除生命周期观察者
        lifecycle?.let {
            lifecycleObserver?.let { observer ->
                it.removeObserver(observer)
            }
        }
    }

    // 实现 LifecycleEventObserver 接口
    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        if (event == lifeEvent) {
            close()
        }
    }
}